#include "thread_event.h"

#ifndef EVT_DBG
#define EVT_DBG(format, argument...)    do{ printf("[ %s ]  %s (line %d) -> " format"\r\n", __FUNCTION__,  __FILE__ ,__LINE__, ##argument ); }while(0)
#endif
#define THREAD_EVENT_PATH	"/tmp/"

static t_event_listen *event_listen_info_malloc(void);
static void event_listen_info_free(t_event_listen *event_listen_info);

/** 
 * @brief 添加一个事件模块，并且初始化
 * @param      num： 初始化事件模块的编号，用于生成key值,需要具备唯一性         
 * 				event_listen_list：链表头成员
 * @return 
 */
int event_module_add_init(int num, t_event_listen *event_listen_list)
{
	int ret = 0;
	if(NULL == event_listen_list){
		EVT_DBG("event_listen_list is null");
		return -1;
	}
	if(num <= 0){
		EVT_DBG("num is fail");
		return -1;
	}
	INIT_LIST_HEAD(&event_listen_list->list);
	//EVT_DBG(" INIT_LIST_HEAD event_listen_list->list %p",&event_listen_list->list);
	//ret = que_create(THREAD_EVENT_PATH, num);
	ret = que_create(NULL, num);
	if(ret < 0){
		EVT_DBG("que_create fail");
	}
	return ret;
}

/** 
 * @brief 删除一个事件模块，并且释放其监听链表的所有资源
 * @param        msqid：事件模块id
 				event_listen_list：链表头成员
 * 
 * @return 
 */
int event_module_del_deinit(int msqid, t_event_listen *event_listen_list)
{
	if(NULL == event_listen_list){
		EVT_DBG("event_listen_list is null");
		return -1;
	}
	struct list_head *pos =NULL,*n=NULL;
	t_event_listen *tmp = NULL;
	list_for_each_safe(pos, n, &event_listen_list->list)
	{
		// 这里我们用list_entry来取得pos所在的结构的指针
		tmp = list_entry(pos, t_event_listen, list);
		if(NULL == tmp){
			break;
		}
		EVT_DBG("del event id %d ", tmp->event_id);
		list_del_init(pos);
		event_listen_info_free(tmp);
	}
	return que_remove(msqid);
}

/** 
 * @brief 事件模块监听列表成员资源申请
 * @param               
 * 
 * @return 
 */
static t_event_listen *event_listen_info_malloc(void)
{
	t_event_listen *p = malloc(sizeof(t_event_listen));
	if(NULL == p){
		goto EXIT;
	}
	memset(p, 0x00, sizeof(t_event_listen));
	return p;
EXIT:
	if(p){
		free(p);
	}
	return NULL;
}

/** 
 * @brief 事件模块监听列表成员资源释放
 * @param               
 * 
 * @return 
 */
static void event_listen_info_free(t_event_listen *event_listen_info)
{
	if(event_listen_info){
		free(event_listen_info);
	}
}


/** 
 * @brief 事件模块中事件id的监听，在监听链表尾部添加该节点
 * @param     event_listen_list：链表头成员
 				event_id：事件id
 				user_data：事件用户参数
 				event_callback_func cb：事件回调函数
 * 
 * @return 
 */
int event_listen(t_event_listen *event_listen_list , int event_id, void *user_data, event_callback_func cb)
{
	if(event_listen_list == NULL){
		return -1;
	}
	t_event_listen *p = event_listen_info_malloc();
	p->event_id = event_id;
	p->user_data = user_data;
	p->cb = cb;
	list_add_tail(&p->list, &event_listen_list->list);
	return 0;
}

/** 
 * @brief 事件模块中事件id的取消监听，从监听链表中删除该节点
 * @param           event_listen_list：链表头成员
 					event_id：事件id
 * 
 * @return 
 */
int event_unlisten(t_event_listen *event_listen_list , int event_id)
{
	if(event_listen_list == NULL){
		return -1;
	}
	struct list_head *pos =NULL,*n=NULL;
	t_event_listen *tmp = NULL;
	list_for_each_safe(pos, n, &event_listen_list->list)
	{
		// 这里我们用list_entry来取得pos所在的结构的指针
		tmp = list_entry(pos, t_event_listen, list);
		if(NULL == tmp){
			break;
		}
		if(tmp->event_id == event_id){
			EVT_DBG("del event id %d ", tmp->event_id);
			list_del_init(pos);
			event_listen_info_free(tmp);
		}
	}

	return 0;
}

/** 
 * @brief 事件模块处理流程，非阻塞，从消息队列中读取数据并且处理
 * @param       msqid：事件模块id
 				event_listen_list：链表头成员
 * 
 * @return 
 */
int event_listen_process(int msqid,t_event_listen *event_listen_list, int is_block)
{
	if(event_listen_list == NULL){
		return -1;
	}
	int ret = -1;
	void *arg = NULL;
	long int event_id = 0; 
	
	uint64_t u64addr;  //64位编译器选择使用//
	uint32_t u32addr;  //32位编译器选择使用//
	if(sizeof(void *) == 8){
		ret = rx_sys_que(msqid, is_block, &event_id, (uint8_t *)&u64addr,sizeof(void *)); 
		arg = (void *)u64addr;
	}
	else if(sizeof(void *) == 4){
		ret = rx_sys_que(msqid, is_block, &event_id, (uint8_t *)&u32addr,sizeof(void *)); 
		arg = (void *)u32addr;
	}
	if(ret <= 0){
		goto EXIT;
	}
	struct list_head *pos =NULL,*n=NULL;
	t_event_listen *tmp = NULL;
	list_for_each_safe(pos, n, &event_listen_list->list)
	{
		// 这里我们用list_entry来取得pos所在的结构的指针
		tmp = list_entry(pos, t_event_listen, list);
		if(NULL == tmp){
			break;
		}
		if(tmp->event_id == event_id){
			if(tmp->cb)tmp->cb(tmp, arg);
		}
	}
EXIT:
	return ret;
}

/** 
 * @brief 事件发送接口
 * @param       msqid：事件模块id
 				event_id：事件id
 				arg:发送事件时带入的参数，由外部申请，内部会有一层浅释放
 * 
 * @return 
 */
int event_msg_send(int msqid,int event_id, void *arg )
{
	int ret = -1;
	ret = tx_sys_que2(msqid, event_id, arg);
	return ret;

}


